package com.codewsq.exer.wait;
/*
* 线程通信：使用wait挂起线程，使用notify方法释放其他线程的挂起状态，将其他线程从wait状态退出
* 下面例子是一个生产者，消费者和门店的逻辑，生产者生产商品，放在门店，门店最多可放商品为20个，消费者消费商品，写一段逻辑
* 思路：
*   生产者生产产品，当门店产品数量不到20时生产产品，增加产品后notify()释放消费者线程使其继续消费，否则停止生产并将该线程wait()挂起
*   消费者消费产品，当门店产品数量大于0时消费产品，减少产品后notify()释放生产者线程使其继续生产，否则停止消费并将该线程wait()挂起，
* */
class Clerk { // 门店店员
    // 产品数量
    private int productCount = 0;

    // 生产产品 ，此时 synchronized的同步监视器为 this
    public synchronized void produce() throws InterruptedException {
        if (productCount < 20) {
            productCount++;
            System.out.println(Thread.currentThread().getName() + "开始生产第" + productCount + "个产品");
            this.notify();
        } else {
            this.wait();
        }


    }
    // 消费产品
    public synchronized void consumption() throws InterruptedException {
        if (productCount > 0) {
            System.out.println(Thread.currentThread().getName() + "开始消费第" + productCount + "个产品");
            productCount--;
            this.notify();
        } else {
            this.wait();
        }

    }
}

// 生产者
class Producer extends Thread {

    private Clerk clerk;

    public Producer(Clerk clerk) {
        this.clerk = clerk;
    }

    @Override
    public void run() {
        System.out.println(getName() + "线程启动");
        while (true) {
            try {
                Thread.sleep(50);
                clerk.produce();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}

// 消费者
class Consumer extends Thread {
    private Clerk clerk;

    public Consumer(Clerk clerk) {
        this.clerk = clerk;
    }

    @Override
    public void run() {
        System.out.println(getName() + "线程启动");
        while (true) {
            try {
                Thread.sleep(100);
                clerk.consumption();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}


public class ProductTest {
    public static void main(String[] args) {
        Clerk clerk = new Clerk();

        Producer p1 = new Producer(clerk);
        p1.setName("生产者1");
        Consumer c1 = new Consumer(clerk);
        c1.setName("消费者1");
        Consumer c2 = new Consumer(clerk);
        c2.setName("消费者2");

        p1.start();
        c1.start();
        c2.start();
    }
}
